<template>
  <el-dialog v-model="visible" :title="title" :close-on-click-modal="false">
    <el-form ref="formRef" :model="modelForm" :rules="rules" :label-width="labelWidth">
      <el-row :gutter="20">
        <el-col
          v-for="item in filteredDialogForm"
          :key="item.value"
          :span="item?.span ? item?.span : span"
        >
          <el-form-item :label="item.label" :prop="item.value">
            <el-input
              v-if="item.type === 'input'"
              v-model.trim="modelForm[item.value]"
              :disabled="unref(item?.disabled)"
              :placeholder="item?.placeholder"
              v-bind="item.otherOption"
            />
            <el-select
              v-else-if="item.type === 'select'"
              v-model="modelForm[item.value]"
              style="width: 100%"
              :placeholder="item?.placeholder"
            >
              <el-option
                v-for="option in item.optionConfig?.options || []"
                :key="option[item.optionConfig?.valueKey || 'value']"
                :label="option[item.optionConfig?.labelKey || 'label']"
                :value="option[item.optionConfig?.valueKey || 'value']"
              />
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer v-if="footerFlag">
      <div class="dialog-footer">
        <gradient-button v-if="resetFlag" :icon="Refresh" @click="reset">重置</gradient-button>
        <gradient-button :icon="Select" @click="saveAndUpdate">保存</gradient-button>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref, computed, watch, reactive, nextTick, unref, type Ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { Select, Refresh } from '@element-plus/icons-vue'
import { CircleCloseFilled } from '@element-plus/icons-vue'
// 定义表单字段类型
export interface FormFieldType {
  value: string
  label?: string
  type?: 'input' | 'select'
  optionConfig?: {
    options?: Record<string, any>
    labelKey?: string
    valueKey?: string
  }
  disabled?: boolean | Ref<boolean>
  isDisplay?: boolean | ((formData: Record<string, any>) => boolean)
  placeholder?: string
  span?: number
  otherOption?: Record<string, any>
  // 新增排序字段，数字越小排序越靠前
  order?: number
}

// 定义props类型
const props = defineProps({
  dialogVisible: {
    type: Boolean,
    default: false,
  },
  title: {
    type: String,
    default: 'Title',
  },
  rules: {
    type: Object as () => FormRules,
    default: () => ({}),
  },
  dialogForm: {
    type: Array as () => FormFieldType[],
    default: () => [],
  },
  dialogData: {
    type: Object as () => Record<string, any>,
    default: () => ({}),
  },
  labelWidth: {
    type: String,
    default: '120px',
  },
  span: {
    type: Number,
    default: 24,
  },
  resetFlag: {
    type: Boolean,
    default: true,
  },
  footerFlag: {
    type: Boolean,
    default: true,
  },
})

// 定义emits类型
const emits = defineEmits(['closed', 'saveAndUpdate'])

// 表单引用
const formRef = ref<FormInstance>()

// 表单数据
const modelForm = ref<Record<string, any>>({})

// 计算属性：对话框可见性
const visible = computed({
  get() {
    return props.dialogVisible
  },
  set(val) {
    emits('closed', val)
  },
})

// 计算属性：过滤需要显示的表单项并按order排序
const filteredDialogForm = computed(() => {
  // 先过滤需要显示的项
  const displayedItems = props.dialogForm.filter((item) => isDisplay(item))

  // 再根据order排序，order值越小越靠前
  return displayedItems.sort((a, b) => {
    // 处理order可能为undefined的情况，默认值设为Infinity排在后面
    const orderA = a.order ?? Infinity
    const orderB = b.order ?? Infinity
    return orderA - orderB
  })
})

// 判断是否显示表单项
const isDisplay = (item: FormFieldType) => {
  const display = item.isDisplay
  if (typeof display === 'boolean') return display
  if (typeof display === 'function') return display(modelForm.value)
  return true // 默认显示
}

// 初始化表单数据
const reset = () => {
  formRef.value?.clearValidate()
  nextTick(() => {
    Object.assign(modelForm.value, props.dialogData)
  })
}

// 保存数据
const saveAndUpdate = () => {
  formRef.value?.validate((valid) => {
    if (valid) {
      emits('saveAndUpdate', { ...modelForm.value })
    }
  })
}

// 监听对话框可见性变化
watch(
  () => props.dialogVisible,
  (newVal) => {
    if (newVal) {
      reset()
    } else {
      modelForm.value = {}
    }
  },
  { immediate: true },
)
</script>

<style lang="scss" scoped>
// 这里可以添加组件特定的样式
.__dialog-header {
  display: flex;
  justify-content: space-between;
  color: #ffffff;
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
</style>
